package com.aplink.generic.google.maps.ui;

import android.content.Context;
import android.location.Location;
import android.os.Bundle;

import com.aplink.generic.util.LogUtil;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;

public class LocationUtil implements
        GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
	public interface CallBack {
		void handleLocationChange(Location location);
	}
	public class LocationOption {
		public LocationUtil create() {
			return LocationUtil.this;
		}

		public LocationOption initLocationClient(Context context) {
			mLocationClient = new LocationClient(context, LocationUtil.this,
			        LocationUtil.this);
			return this;
		}

		public LocationOption setFastestInterval(int fastestInterval) {
			mLocationRequest.setFastestInterval(fastestInterval);
			return this;
		}

		public LocationOption setInterval(int interval) {
			mLocationRequest.setInterval(interval);
			return this;
		}

		public LocationOption setLocationListener(
		        LocationListener locationListener) {
			mLocationListener = locationListener;
			return this;
		}

		public LocationOption setPriority(int priority) {
			mLocationRequest.setPriority(priority);
			return this;
		}
	}
	private static LocationUtil sInstance = null;
	public static LocationUtil getInstance() {
		synchronized (LocationUtil.class) {
			if (sInstance == null) {
				sInstance = new LocationUtil();
			}
			return sInstance;
		}
	}
	private CallBack mCallBack;
	private Location mCurrentLocation;

	private LocationClient mLocationClient;

	private LocationListener mLocationListener;

	private LocationRequest mLocationRequest;

	public LocationOption builder() {
		mLocationRequest = LocationRequest.create();
		return new LocationOption();
	}

	public void connect() {
		synchronized (LocationUtil.class) {
			if (mLocationClient != null) {
				if (!mLocationClient.isConnected()) {
					mLocationClient.connect();
				}
			}
		}
	}

	public void disconnect() {
		synchronized (LocationUtil.class) {
			if (mLocationClient != null) {
				if (mLocationClient.isConnected()) {
					mLocationClient.disconnect();
				}
			}
		}
	}

	public void dispose() {
		disconnect();
		sInstance = null;
	}

	public Location getCurrentLocation() {
		return mCurrentLocation;
	}

	public LocationUtil getDefaultLocationService(CallBack callBack,
	        Context context) {
		mCallBack = callBack;
		return builder().setInterval(5)
		        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
		        .setFastestInterval(5).setLocationListener(this)
		        .initLocationClient(context).create();
	}

	public boolean isConnected() {
		if (mLocationClient != null) {
			return mLocationClient.isConnected();
		}
		return false;
	}

	@Override
	public void onConnected(Bundle connectionHint) {
		startPeriodicUpdates();
	}

	@Override
	public void onConnectionFailed(ConnectionResult result) {

	}

	@Override
	public void onDisconnected() {
		stopPeriodicUpdates();
	}

	@Override
	public void onLocationChanged(Location location) {
		LogUtil.info(LogUtil.TAG_LOCATION, location.toString(),
		        "onLocationChanged", getClass());
		mCurrentLocation = location;
		mCallBack.handleLocationChange(location);
	}

	public void startPeriodicUpdates() {
		mLocationClient.requestLocationUpdates(mLocationRequest,
		        mLocationListener);
	}

	public void stopPeriodicUpdates() {
		mLocationClient.removeLocationUpdates(mLocationListener);
	}

}
